#!/usr/bin python3
# -*- encoding: utf-8 -*-
"""
@author: 关河九州
@contact: 
@software: PyCharm
@file: base_api
@time: 2022/2/18 16:40
"""
import os
import json as js
import allure
import requests
import simplejson
from loguru import logger
from requests.adapters import HTTPAdapter
from urllib3 import Retry

from common.handle_assert import HandleAssert
from common.handle_path import CONF_DIR
from common.utils import Utils

HTTP_TIMEOUT = 60
RETRY_TIMES = 3

""" =============== 封装通用的接口流程方法 公共方法 =============== """

''' 
base_api的核心只关心api的通用逻辑，代表的是通用接口的封装，用于跟各个api提供支持，如发送http请求、读取
yaml文件、替换数据等公共方法，无关业务逻辑
'''


class BaseApi:
    # 配置文件路径
    conf_path = os.path.join(CONF_DIR, 'config.yaml')
    # 配置文件数据
    conf_data = Utils().handle_yaml(conf_path)
    # print(conf_data)
    host = conf_data['env']['host']  # 服务器地址
    headers = conf_data['request_headers']['headers']  # 信息头
    account = conf_data['account']  # 账号
    investor_account = conf_data['investor_account']  # 账号
    mysql_conf = conf_data['mysql']  # 数据库

    retry = Retry(connect=RETRY_TIMES, backoff_factor=0.5)
    adapter = HTTPAdapter(max_retries=retry)

    def send_api(self, data: dict):
        """
        发送请求
        :param data: 请求数据
        :return:
        """

        def dumps(body):
            return js.dumps(js.loads(body), indent=4, ensure_ascii=False)

        try:
            self.__api_log(**data)
            response = requests.request(**data)
            info = ["响应结果为: " + str(response.status_code)]
            if response.request.body:
                if isinstance(response.request.body, bytes):
                    request_body = response.request.body.decode("unicode-escape", errors="ignore")
                    try:
                        info.insert(2, "Body:\n\n" + dumps(request_body))
                    except js.decoder.JSONDecodeError:
                        info.insert(2, "Body:\n\n" + request_body)
                else:
                    info.insert(2, "Body:\n\n" + response.request.body)

            try:
                info.append("Response Body:\n\n" + js.dumps(response.json(), indent=4, ensure_ascii=False))
            except (js.decoder.JSONDecodeError, simplejson.errors.JSONDecodeError):
                info.append("Response Body:\n\n" + response.text)
            logger.info("\n".join(info))
            allure.attach("\n\n".join(info), "请求响应信息")
            return response
        except Exception as e:
            logger.error(f'发送请求失败，请求参数为：{data}')
            logger.exception(f'发生的错误为：{e}')
            raise e

    @staticmethod
    def __api_log(method, url, headers=None, params=None, json=None):
        """
        接口请求日志
        :param method: 请求方式
        :param url: 请求地址
        :param headers: 请求头
        :param params: 请求参数
        :param json: 请求体
        :return:
        """
        logger.info(f"请求方式：{method}")
        logger.info(f"请求地址：{url}")
        logger.info(f"请求头：{headers}")
        logger.info(f"请求参数：{params}")
        logger.info(f"请求体：{json}")

    @staticmethod
    def get_yaml(file_name):
        """
        读取yaml文件
        :param file_name: 文件路径名称
        :return: dict
        """
        return Utils.handle_yaml(file_name)

    @staticmethod
    def get_token(response):
        """
        处理并提取token
        :param response:
        :return:
        """
        return Utils.handle_token(response)

    @staticmethod
    @allure.step('数据替换')
    def template(source_data: str, data: dict):
        """
        替换数据
        :param source_data: 源数据
        :param data: 替换内容，如{data:new_data}
        :return:
        """

        return Utils.handle_template(source_data, data)

    @staticmethod
    def to_two_decimal(data):
        """
        将整数或浮点数转化为两位数小数
        :param data:
        :return:
        """
        return Utils.handle_decimal(data)

    @staticmethod
    def random_phone():
        """
        生成随机手机号
        :return:
        """
        return Utils.handle_random_phone()

    @staticmethod
    def random_name():
        """
        生成随机名字
        :return:
        """
        return Utils.handle_random_name()

    @staticmethod
    def random_address():
        """
        生成随机地址
        :return:
        """
        return Utils.handle_random_address()

    @staticmethod
    def assert_equal(ex, re):
        """
        断言相等
        :param ex:预期结果
        :param re:实际结果
        :return:
        """
        return HandleAssert.eq(ex, re)

    @staticmethod
    def assert_contains(content, target):
        """
        断言包含
        :param content: 文本内容
        :param target: 目标文本
        :return:
        """
        return HandleAssert.contains(content, target)


if __name__ == '__main__':
    a = BaseApi()
    a.random_name()
